package com.example.transaction;

import com.example.entity.User;
import com.example.service.UserService;
import com.example.spring.aopbug.Metrics;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @author houyangfan
 * @version 1.0
 * @date 2022/7/15 18:02
 */
@RestController
@RequestMapping("/transaction")
@Slf4j
public class TransactionBug {

    @Autowired
    private UserService userService;

    /**
     * 异常无法传播出方法，导致事务无法回滚, 如果希望自己捕获异常进行处理的话，可以手动设置回滚
     * @param name
     * @return
     */
    @GetMapping("wrong1")
    public User test1(@RequestParam("name") String name) {
        userService.insert(name);
        return null;
    }

    /**
     * 事务默认只回滚非检查性异常，如果想回滚检查性异常 可以指定rollbackfor为Exception 来设置任何异常都可以回滚
     * @param name
     * @return
     * @throws IOException
     */
    @GetMapping("wrong2")
    public User test2(@RequestParam("name") String name) throws IOException {

        userService.createUserWrong2(name);
        return null;
    }
    /**
     *  该示例是，在有多个数据库操作的场景下，实现出异常的操作正常回滚但是之前执行的操作不回滚
     *  比如：在注册用户的时候，同时添加主用户和子用户，主用户注册成功之后，接着添加子用户，如果子用户添加失败，但是主用户依旧要添加不需要回滚
     *  解决方法： 1. 主方法（insertMainSubUser）上不加事务，子方法（subUserService.createSubUser）上添加事务
     *           2. 主方法上添加事务，子方法上的@Transaction可以指定参数新启一个事务
     * @param name
     */
    @GetMapping("wrong3")
    public User test3(@RequestParam("name") String name) {

        userService.insertMainSubUser(name);
        return null;
    }


    /**
     * 该实例 结合aop中的aspect 测试 切面功能
     * @param name
     * @return
     */
    @GetMapping("testAspect")
    @Metrics
    public User testAspect(@RequestParam("name") String name) {
        System.out.println("1111");
        try {
            userService.insert(name);
            return null;
        }catch (Exception ex){
            log.error("执行失败："+ ex);
        }
        return null;
    }
}
